#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/printk.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include "dbg_out.h"

static int major = 0;
static int lastMinor = 0;
static struct class* cls = NULL;

static int fops_open(struct inode* i_node, struct file* f)
{
    DBG_INFO("fops open");
    return 0;
}

static int fops_close(struct inode* i_node, struct file* f)
{
    DBG_INFO("fops close");
    return 0;
}

static ssize_t fops_read(struct file* f, char __user* data, size_t size, loff_t* loff)
{
    DBG_INFO("fops read");
    return 0;
}

static ssize_t fops_write(struct file* f, const char __user* data, size_t size, loff_t* loff)
{
    DBG_INFO("fops write");
    return -1;
}

struct file_operations driver_fops = {
    .open = fops_open,
    .release = fops_close,
    .read = fops_read,
    .write = fops_write,
};

int plat_probe(struct platform_device* plat_dev)
{
    DBG_INFO("plat_drv probe device: %s", plat_dev->name);

    if (cls == NULL)
    {
        cls = class_create(THIS_MODULE, "plat_cls");
        ERROR_OUT_IF(IS_ERR(cls), NULL, -EINVAL, "class create error");
    }

    if (major == 0)
    {
        dev_t tmpdev = 0;
        alloc_chrdev_region(&tmpdev, 0, 255, "platform_test");
        ERROR_OUT_IF(tmpdev == 0, NULL, -ENOMEM, "major request fail");
        major = MAJOR(tmpdev);
    }

    // devm_kmalloc()

    // device_create(cls, NULL, MKDEV(major, lastMinor), NULL, "platDev%d", lastMinor);

    return 0;
}

int plat_remove(struct platform_device* plat_dev)
{
    DBG_INFO("plat_drv remove dev: %s", plat_dev->name);
    device_destroy(cls, plat_dev->dev.devt);
    return 0;
}

void plat_shutdown(struct platform_device* plat_dev)
{
    
}

int plat_suspend(struct platform_device* plat_dev, pm_message_t state)
{
    
}

int plat_resume(struct platform_device* plat_dev)
{
    
}

struct of_device_id id_table[] = {
    {.compatible = "zzh,platdev"},
    {}
};

struct platform_driver plat_drv = {
    .probe = plat_probe,
    .remove = plat_remove,
    
    .suspend = plat_suspend,
    .resume = plat_resume,
    
    .driver = {
        .name = "plat_dev",
        .of_match_table = id_table
    },
};

module_platform_driver(plat_drv);

MODULE_DESCRIPTION("test module");
MODULE_AUTHOR("zzh");
MODULE_LICENSE("GPL");
